package com.ruoyi.common.workflow.utils;

import cn.hutool.core.util.ObjectUtil;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.JsonUtils;
import com.ruoyi.common.core.utils.SpringUtils;
import com.ruoyi.common.workflow.enums.BusinessStatusEnum;
import com.ruoyi.common.workflow.service.IBusinessStatusService;
import com.ruoyi.common.workflow.service.INodeAssigneeService;
import com.ruoyi.common.workflow.service.IWorkflowService;
import com.ruoyi.workflow.api.domain.ActBusinessStatus;
import com.ruoyi.workflow.api.domain.ActNodeAssignee;
import com.ruoyi.workflow.api.domain.vo.FieldList;
import com.ruoyi.workflow.api.domain.vo.TaskModel;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.ruoyi.common.workflow.constant.FlowConstant.ACT_BUSINESS_STATUS;
import static com.ruoyi.common.workflow.constant.FlowConstant.ACT_NODE_ASSIGNEE;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class FlowableUtils {

    private static final IBusinessStatusService BUSINESS_STATUS_SERVICE = SpringUtils.getBean(IBusinessStatusService.class);

    private static final INodeAssigneeService NODE_ASSIGNEE_SERVICE = SpringUtils.getBean(INodeAssigneeService.class);

    private static final IWorkflowService iWorkflowService = SpringUtils.getBean(IWorkflowService.class);


    /**
     * @description: 设置业务流程参数
     * @param: obj 对象
     * @param: id 主键id
     * @author: gssong
     * @date: 2022/1/16
     */
    public static void setStatusFieldValue(Object obj, String id) {
        Class<?> claszz = obj.getClass();
        ActBusinessStatus actBusinessStatus = BUSINESS_STATUS_SERVICE.getInfoByBusinessKey(id);
        Field businessStatus;
        try {
            businessStatus = claszz.getDeclaredField(ACT_BUSINESS_STATUS);
            businessStatus.setAccessible(true);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
            throw new ServiceException("未找到" + ACT_BUSINESS_STATUS + "属性：" + e.getMessage());
        }
        try {
            if (ObjectUtil.isNotEmpty(actBusinessStatus)) {
                businessStatus.set(obj, actBusinessStatus);
            } else {
                ActBusinessStatus status = new ActBusinessStatus();
                status.setStatus(BusinessStatusEnum.DRAFT.getStatus());
                businessStatus.set(obj, status);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException("设置流程状态失败：" + e.getMessage());
        }
    }

    /**
     * @description: 设置业务流程参数
     * @param: obj 对象
     * @param: idList 主键集合
     * @param: fieldName 主键属性名称
     * @return: void
     * @author: gssong
     * @date: 2022/9/6
     */
    public static void setStatusListFieldValue(Object obj, List<String> idList, String fieldName) {
        List<ActBusinessStatus> actBusinessStatusList = BUSINESS_STATUS_SERVICE.getListInfoByBusinessKey(idList);
        if (obj instanceof Collection) {
            Collection<?> collection = (Collection<?>) obj;
            for (Object o : collection) {
                if (o != null) {
                    Class<?> claszz = o.getClass();
                    Field businessStatus;
                    Field fieldInfo;
                    String fieldValue;
                    try {
                        businessStatus = claszz.getDeclaredField(ACT_BUSINESS_STATUS);
                        businessStatus.setAccessible(true);
                    } catch (NoSuchFieldException e) {
                        e.printStackTrace();
                        throw new ServiceException("未找到" + ACT_BUSINESS_STATUS + "属性：" + e.getMessage());
                    }
                    try {
                        fieldInfo = claszz.getDeclaredField(fieldName);
                        fieldInfo.setAccessible(true);
                        fieldValue = fieldInfo.get(o).toString();
                    } catch (NoSuchFieldException | IllegalAccessException e) {
                        e.printStackTrace();
                        throw new ServiceException("未找到" + fieldName + "属性：" + e.getMessage());
                    }
                    try {
                        ActBusinessStatus actBusinessStatus = actBusinessStatusList.stream().filter(e -> e.getBusinessKey().equals(fieldValue)).findFirst().orElse(null);
                        if (ObjectUtil.isNotEmpty(actBusinessStatus)) {
                            businessStatus.set(o, actBusinessStatus);
                        } else {
                            ActBusinessStatus status = new ActBusinessStatus();
                            status.setStatus(BusinessStatusEnum.DRAFT.getStatus());
                            businessStatus.set(o, status);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        throw new ServiceException("设置流程状态失败：" + e.getMessage());
                    }
                }
            }
        }
    }

    /**
     * @description: 设置流程节点人员设置对象
     * @param: obj 对象
     * @param: taskId 任务id
     * @author: gssong
     * @date: 2022/11/27
     */
    public static void setActNodeAssignee(Object obj, String taskId) {
        TaskModel task = iWorkflowService.getCurrentTask(taskId);
        if (task != null) {
            ActNodeAssignee actNodeAssignee = NODE_ASSIGNEE_SERVICE.getInfoSetting(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
            if (actNodeAssignee != null && StringUtils.isNotBlank(actNodeAssignee.getFieldListJson())) {
                List<FieldList> fieldLists = JsonUtils.parseArray(actNodeAssignee.getFieldListJson(), FieldList.class);
                Map<String, FieldList> collectMap = fieldLists.stream().collect(Collectors.toMap(FieldList::getField, Function.identity()));
                actNodeAssignee.setFieldMap(collectMap);
                Class<?> claszz = obj.getClass();
                Field nodeAssignee;
                try {
                    nodeAssignee = claszz.getDeclaredField(ACT_NODE_ASSIGNEE);
                    nodeAssignee.setAccessible(true);
                } catch (NoSuchFieldException e) {
                    e.printStackTrace();
                    throw new ServiceException("未找到" + ACT_NODE_ASSIGNEE + "属性：" + e.getMessage());
                }
                try {
                    nodeAssignee.set(obj, actNodeAssignee);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                    throw new ServiceException("设置流程状态失败：" + e.getMessage());
                }
            }
        }
    }

}
